---
description:
  Learn how to use Apollo to attach GraphQL query results to your Angular UI with standard GraphQL
  queries. Cache the results and use QueryRef to manage the watched query. Optimize queries by using
  options, such as variables, and display data with AsyncPipe.
---

import { Callout } from '@theguild/components';

# Queries

On this page, you can learn how to use Apollo to attach GraphQL query results to your Angular UI.
This guide assumes some familiarity with GraphQL itself. You can read about GraphQL queries
themselves in detail at [graphql.org](http://graphql.org/docs/queries/).

One of our core values is "it's just GraphQL." When using Apollo Client, you don't have to learn
anything special about the query syntax, since everything is just standard GraphQL. Anything you can
type into the GraphQL query IDE, you can also put into your Apollo Client code.

## Basic Queries

When we are using a basic query, we can use the `Apollo.watchQuery` method in a very simple way. We
simply need to parse our query into a GraphQL document using the `gql` tag from `apollo-angular`
library.

For instance, in our example, we want to display a list of posts in `Posts` component:

```ts
import { Apollo, gql } from 'apollo-angular';
import { Subscription } from 'rxjs';
import { Component, OnDestroy, OnInit } from '@angular/core';

// We use the gql tag to parse our query string into a query document
const GET_POSTS = gql`
  query GetPosts {
    posts {
      id
      title
    }
  }
`;

@Component({
  // ...
})
class PostsComponent implements OnInit, OnDestroy {
  loading: boolean;
  posts: any;

  private querySubscription: Subscription;

  constructor(private readonly apollo: Apollo) {}

  ngOnInit() {
    this.querySubscription = this.apollo
      .watchQuery<any>({
        query: GET_POSTS,
      })
      .valueChanges.subscribe(({ data, loading }) => {
        this.loading = loading;
        this.posts = data.posts;
      });
  }

  ngOnDestroy() {
    this.querySubscription.unsubscribe();
  }
}
```

The `watchQuery` method returns a `QueryRef` object which has the `valueChanges` property that is an
`Observable`.

We can see that the result object contains `loading`, a Boolean indicating if the query is
"in-flight." The observable will only emit once when the query is complete, and `loading` will be
set to false unless you set the `watchQuery` parameters `notifyOnNetworkStatusChange` to true. Once
the query has completed, it will also contain a `data` object with `posts`, the field we've picked
out in `GetPosts` operation.

It's also possible to fetch data only once. The `query` method of `Apollo` service returns an
`Observable` that also resolves with the same result as above.

Imagine you have two views (routes), one of them has the `Posts` component. When you switch between
views, you'll notice that the list of posts loads instantly the second time. This is the Apollo
cache at work!

### What is `QueryRef`

As you know, `Apollo.query` method returns an Observable that emits a result, just once.
`Apollo.watchQuery` also does the same, except it can emit multiple results. (The GraphQL query
itself is still only sent once, but the `watchQuery` observable can also update if, for example,
another query causes the object to be updated within Apollo Client's global cache.)

So why doesn't `Apollo.watchQuery` expose an Observable?

Apollo service and ApolloClient share pretty much the same API. It makes things easy to understand
and use. No reason to change it.

In `ApolloClient.watchQuery` returns an Observable, but not a standard one, it contains many useful
methods (like `refetch()`) to manipulate the watched query. A normal Observable, has only one
method, `subscribe()`.

To use that Apollo's Observable in RxJS, we would have to drop those methods. Since they are
necessary to use Apollo to its full potential, we had to come up with a solution.

This is why we created `QueryRef`.

The API of `QueryRef` is very simple. It has the same methods as the Apollo Observable we talked
about. To subscribe to query results, you have to access its `valueChanges` property which exposes a
clean RxJS Observable.

It's worth mentioning that `QueryRef` accepts two generic types.

## Providing `options`

The `watchQuery` and `query` methods expect one argument, an object with options. If you want to
configure the query, you can provide any available option in the same object where the `query` key
lives.

If your query takes variables, this is the place to pass them in:

```typescript
// Suppose our profile query took an avatar size
const GET_POSTS_OF_AUTHOR = gql`
  query GetPostsOfAuthor($authorId: Int!) {
    postsOf(authorId: $authorId) {
      id
      title
    }
  }
`;

@Component({
  // ...
})
class PostsOfUserComponent implements OnInit, OnDestroy {
  posts: any;

  private querySubscription: Subscription;

  ngOnInit() {
    this.querySubscription = this.apollo
      .watchQuery({
        query: GET_POSTS_OF_AUTHOR,
        variables: {
          authorId: 12,
        },
      })
      .valueChanges.subscribe(({ data }) => {
        this.posts = data.postsOf;
      });
  }
  ngOnDestroy() {
    this.querySubscription.unsubscribe();
  }
}
```

## Using with `AsyncPipe`

In Angular, the simplest way of displaying data that comes from Observable is to put `AsyncPipe` on
top of the property inside the UI. You can also achieve this with Apollo.

<Callout type="warning">
  **Note**: Using async pipe more than once in your template will trigger the query for each pipe.
  To avoid this situation, subscribe to the data in the component, and display the data from the
  component's property.
</Callout>

An Observable returned by `watchQuery().valueChanges` holds the actual result under the `data`
field, so you can not directly access one of the properties of that object.

```ts
import { Apollo, gql } from 'apollo-angular';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Component, OnInit } from '@angular/core';

const GET_FEED = gql`
  query GetFeed {
    authors {
      id
      firstName
      lastName
    }
    posts {
      it
      title
    }
  }
`;

@Component({
  template: `
    <ul>
      @for (post of posts | async; track post.id) {
        <li>
          {{ post.title }}
        </li>
      }
    </ul>
  `,
})
class FeedComponent implements OnInit {
  posts: Observable<any>;

  constructor(private readonly apollo: Apollo) {}

  ngOnInit() {
    this.posts = this.apollo
      .watchQuery({ query: GET_FEED })
      .valueChanges.pipe(map(result => result.data.posts));
  }
}
```

The result of the query has this structure:

```json
{
  "data": {
    "authors": [ ... ],
    "posts": [ ... ]
  }
}
```

Without using the `map` operator, you would get the whole object instead of only the `data.posts`.

## Updating Cached Query Results

Caching query results is handy and easy to do, but sometimes you want to make sure that cached data
is up to date with your server. Apollo Client supports two strategies for this: **polling** and
**refetching**.

### Polling

Polling provides near-real-time synchronization with your server by causing a query to execute
periodically at a specified interval. To enable polling for a query, pass a `pollInterval`
configuration option to the `Apollo.watchQuery` with an interval in milliseconds:

```ts
import { Apollo, gql } from 'apollo-angular';
import { Subscription } from 'rxjs';
import { Component, OnDestroy, OnInit } from '@angular/core';

// We use the gql tag to parse our query string into a query document
const GET_POSTS = gql`
  query GetPosts {
    posts {
      id
      title
    }
  }
`;

@Component({
  // ...
})
class PostsComponent implements OnInit, OnDestroy {
  loading: boolean;
  posts: any;

  private querySubscription: Subscription;

  constructor(private readonly apollo: Apollo) {}

  ngOnInit() {
    this.querySubscription = this.apollo
      .watchQuery<any>({
        query: GET_POSTS,
        pollInterval: 500,
      })
      .valueChanges.subscribe(({ data, loading }) => {
        this.loading = loading;
        this.posts = data.posts;
      });
  }

  ngOnDestroy() {
    this.querySubscription.unsubscribe();
  }
}
```

By setting the `pollInterval` to `500`, you'll fetch the list of posts from the server every 0.5
seconds. Note that if you set `pollInterval` to `0`, the query will **not** poll.

<Callout>
  You can also start and stop polling dynamically with the `startPolling` and `stopPolling`
  functions that are available in the `QueryRef` object returned by `Apollo.watchQuery()`
</Callout>

### Refetching

Refetching enables you to refresh query results in response to a particular user action, as opposed
to using a fixed interval.

Let's add a button to our `Posts` component that calls our query's refetch function whenever it's
clicked.

<Callout>
  You can optionally provide a new `variables` object to the refetch function. If you don't (as is
  the case in the following example), the query uses the same variables that it used in its previous
  execution.
</Callout>

```typescript
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { Apollo, QueryRef, gql } from 'apollo-angular';

// We use the gql tag to parse our query string into a query document
const GET_POSTS = gql`
  query GetPosts {
    posts {
      id
      title
    }
  }
`;

@Component({ ... })
class PostsComponent implements OnInit, OnDestroy {
  loading: boolean;
  posts: any;
  postsQuery: QueryRef<any>;

  private querySubscription: Subscription;

  constructor(private readonly apollo: Apollo) {}

  ngOnInit() {
    this.postsQuery = this.apollo.watchQuery<any>({
      query: GET_POSTS,
      pollInterval: 500,
    });
    this.querySubscription = this.postsQuery
      .valueChanges
      .subscribe(({ data, loading }) => {
        this.loading = loading;
        this.posts = data.posts;
      });
  }

  refresh() {
    this.postsQuery.refetch()
  }

  ngOnDestroy() {
    this.querySubscription.unsubscribe();
  }
}
```

Call the `refresh` method and notice that the UI updates with a new dog photo. Refetching is an
excellent way to guarantee fresh data, but it introduces some complexity with loading state. In the
next section, we'll cover strategies for handling complex loading and error state.

## Inspecting Error States

You can customize your query error handling by providing the `errorPolicy` configuration option to
`Apollo.watchQuery` or `Apollo.query`. The default value is `none`, which tells Apollo Angular to
treat all GraphQL errors as runtime errors. In this case, Apollo Angular discards any query response
data returned by the server and sets the error property in the result object to true.

If you set `errorPolicy` to `all`, Apollo Angular does not discard query response data, allowing you
to render partial results.

## Loading State

Every response you get from `Apollo.watchQuery()` contains the `loading` property. The option
[`notifyOnNetworkStatusChange`](https://www.apollographql.com/docs/react/data/queries#queryhookoptions-interface-notifyonnetworkstatuschange)
defaults to `true`. That means the observable will emit immediately and synchronously with
`loading: true` and `data: undefined`. When the XHR is completed, the observable will emit with
`loading: false` and with a defined `result`.

If you prefer to be notified only when result is available, and you are not interested in loading
state, then you can configure `notifyOnNetworkStatusChange` to `false`, globally when constructing
`ApolloClient` of for a specific query only. Something like this:

```ts filename="app.config.ts"
import { provideApollo } from 'apollo-angular';
import { HttpLink } from 'apollo-angular/http';
import { inject } from '@angular/core';
import { InMemoryCache } from '@apollo/client';

provideApollo(() => {
  return {
    link: inject(HttpLink).create({ uri: '/graphql' }),
    cache: new InMemoryCache(),
    defaultOptions: {
      watchQuery: {
        notifyOnNetworkStatusChange: false,
      },
    },
  };
});
```
